import Vue from 'vue'
import axios from 'axios'
import cookie from 'vue-cookie'
import router from '@/router'
import store from '@/store'
import qs from 'qs' // 字符串处理
import merge from 'lodash/merge' // 合并对象工具
import {
	clearLoginInfo
} from '@/utils/index'
import {
	formatDate,
	YyMmDdToTimes
} from '@/utils/time-util'
import {
	localStorageSet,
	localStorageGet
} from '@/utils/storage-util'
import {
	refreshToken
} from '@/http/module/oauth'

let Message = Vue.prototype.$Message
let LoadingBar = Vue.prototype.$LoadingBar
let needLoadingRequestCount = 0
// 被挂起的请求数组
let subscribes = []
// 是否有请求在刷新token
localStorageSet('IS_REFRESH_TOKEN', false)

// 开始加载提示框
function startLoading() {
	if (LoadingBar) {
		LoadingBar.start()
	}
}
// 结束加载提示框
function endLoading() {
	if (LoadingBar) {
		LoadingBar.finish()
	}
}
// 请求堆积开始加载提示框
export function showFullScreenLoading(config) {
	console.debug('showFullScreenLoading needLoadingRequestCount start >> ' + needLoadingRequestCount)
	if (needLoadingRequestCount === 0) {
		if (config.loading === true) {
			startLoading()
		}
	}
	needLoadingRequestCount++
	console.debug('showFullScreenLoading needLoadingRequestCount end >> ' + needLoadingRequestCount)
}
// 请求消减关闭加载提示框
export function tryHideFullScreenLoading() {
	console.debug('tryHideFullScreenLoading needLoadingRequestCount start >> ' + needLoadingRequestCount)
	if (needLoadingRequestCount <= 0) return
	needLoadingRequestCount--
	if (needLoadingRequestCount === 0) {
		endLoading()
	}
	console.debug('tryHideFullScreenLoading needLoadingRequestCount end >> ' + needLoadingRequestCount)
}
// push所有token过期后的请求到数组中
function subscribeTokenRefresh(i) {
	subscribes.push(i)
}
// 用新的token发起请求
function reloadSubscribe(i) {
	subscribes.map(cb => cb(i))
}
// 身份信息无效停止刷新token
function stopRefreshToken() {
	needLoadingRequestCount = 0
	endLoading()
	subscribes = []
}
// token是否过期
function isTokenExpired() {
	let expiredTime = cookie.get('expiredTime')
	let refreshToken = cookie.get('refreshToken')
	if (expiredTime && refreshToken) {
		let nowTime = new Date().getTime()
		return (expiredTime - nowTime) / 1000 < 6 * 60
	} else {
		// 不存在，需要重新登录
		stopRefreshToken()
	}
	return false
}
// token过期处理
function isRefreshToken(token, config) {
	if (!token) {
		let refreshToken = cookie.get('refreshToken')
		if (isTokenExpired()) {
			let isRefreshToken = localStorageGet('IS_REFRESH_TOKEN')
			if (!isRefreshToken || isRefreshToken === 'false') {
				localStorageSet('IS_REFRESH_TOKEN', true)
				refreshToken(refreshToken).then(res => {
					localStorageSet('IS_REFRESH_TOKEN', false)
					if (res && res.code === 10000) {
						let data = res.data
						let expiredTime = formatDate(new Date().getTime() + (data.expiration * 1000), 'yyyy-MM-dd HH:mm:ss')
						cookie.set('accessToken', data.accessToken, {
							'expires': expiredTime
						})
						cookie.set('expiredTime', YyMmDdToTimes(expiredTime))
						reloadSubscribe(data.accessToken)
					} else {
						subscribes = []
						clearLoginInfo()
						directLogin()
					}
				}).catch(() => {
					subscribes = []
					clearLoginInfo()
					directLogin()
				})
			}
			let retry = new Promise((resolve, reject) => {
				subscribeTokenRefresh((newToken) => {
					config.headers['Authorization'] = newToken
					resolve(config)
				})
			})
			return retry
		}
	}
	showFullScreenLoading(config)
}
// 直接登录
function directLogin() {
	router.push({
		path: '/login',
		query: {
			redirectUrl: window.location.href.split('#')[1] || ''
		}
	})
}

const http = axios.create({
	baseURL: process.env.VUE_APP_BASE_API,
	timeout: 1000 * 30, // 请求超时时间
	withCredentials: false, // 请求跨域时候不在请求中携带cookie
	headers: {
		'Content-Type': 'application/json;charset=utf-8'
	}
})
// 请求拦截
http.interceptors.request.use(config => {
	// 处理请求之前的配置
	const token = cookie.get('accessToken')
	config.headers['Authorization'] = token
	// 是否显示加载框
	if (config.loading === undefined) {
		config['loading'] = true
	}

	// 如果不需要token的接口直接返回
	if (config.url.startsWith('/oauth')) {
		return config
	}
	// 是否刷新token
	let retry = isRefreshToken(token, config)
	if (retry) return retry

	return config
}, error => {
	tryHideFullScreenLoading()
	console.log('error', error)
	Message.error({
		content: error,
		duration: 3
	})
	// 请求失败的处理
	return Promise.reject(error)
})

// 响应拦截
http.interceptors.response.use(res => {
	return resStateProcess(res)
}, error => {
	let res = error.response
	if (!res) {
		return
	}
	
	resStateProcess(res)
	
	return Promise.reject(error)
})
// 相应状态处理
function resStateProcess(res) {
	tryHideFullScreenLoading()
	
	if (!res.data) {
		return
	}
	let errorInfo = res.data.error
	let kictOutMsg = '您的账号在其他地方进行登录，如果不是本人操作，请修改密码！'
	
	console.info('response status error >> ' + res.status)
	switch (res.status) {
		case 200:
			break;
		case 203:
			clearLoginInfo()
			switch (res.data.code) {
				case 10008:
					if (cookie.get('accessToken')) {
						message(kictOutMsg)
					}
					break;
			}
			break;
		case 401:
			clearLoginInfo()
			if (cookie.get('accessToken')) {
				message(kictOutMsg)
			} else {
				message(errorInfo)
			}
			break;
		case 502:
			message('网络连接超时，请稍后再试！')
			break;
		default:
			message(errorInfo)
			break;
	}
	
	return res.data
}
// 统一异常消息
function message(content = '') {
	let route = router.currentRoute
	let ignorePageNames = store.getters.system_ignore
	for (let ignorePageName of ignorePageNames) {
		if (route.name == ignorePageName) {
			continue
		}
		Message.error(content)
	}
}


// 默认参数
http.defaultParams = {
	'time': new Date().getTime()
}
// 获取地址
http.abortUrl = (apiKey, params = {}, openDefaultParams = true) => {
	let url = process.env.VUE_APP_BASE_API + apiKey
	params = openDefaultParams ? merge(params, http.defaultParams) : params
	return url + qs.stringify(params, {
		addQueryPrefix: true,
		arrayFormat: 'repeat',
		allowDots: true
	})
}
// query请求参数处理
http.queryData = (params = {}, openDefaultParams = true, isFormat = false) => {
	params = openDefaultParams ? merge(params, http.defaultParams) : params
	if (isFormat) {
		return qs.stringify(params, {
			arrayFormat: 'repeat',
			allowDots: true
		})
	}
	return params
}
// json请求参数处理
http.jsonData = (data = {}, openDefaultdata = true) => {
	data = openDefaultdata ? merge(data, http.defaultParams) : data
	return JSON.stringify(data)
}
// form请求参数处理
http.formData = (data = {}, openDefaultdata = true) => {
	data = openDefaultdata ? merge(data, http.defaultParams) : data
	return qs.stringify(data)
}
// 根据路径获取方法
http.getApiFun = (system, path) => {
	let levels = path.split('.')
	let fun = system.$api
	for (let level of levels) {
		fun = fun[level]
	}
	
	return fun
}

Vue.prototype.$http = http

export default http
